"""
Flask扩展初始化模块
"""
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager
from flask_cors import CORS
import logging
from logging.handlers import RotatingFileHandler
import os


# 初始化扩展
db = SQLAlchemy()
jwt = JWTManager()
cors = CORS()


def init_extensions(app: object) -> None:
    """初始化所有Flask扩展"""
    
    # 数据库
    db.init_app(app)
    
    # JWT认证
    jwt.init_app(app)

    # blueprint
    from app.routes.auth import auth_bp
    from app.routes.devices import devices_bp
    from app.routes.treatments import treatments_bp
    from app.routes.user_routes import user_bp
    from app.routes.dashboard import dashboard_bp
    from app.routes.system import system_bp
    from app.routes.music import music_bp
    from app.routes.upload import upload_bp
    from app.routes.videos import videos_bp
    from app.routes.faq import faq_bp
    from app.routes.contact import contact_bp
    from app.routes.about import about_bp


    app.register_blueprint(auth_bp)
    app.register_blueprint(devices_bp)
    app.register_blueprint(treatments_bp)
    app.register_blueprint(user_bp)
    app.register_blueprint(dashboard_bp)
    app.register_blueprint(system_bp)
    app.register_blueprint(music_bp)
    app.register_blueprint(faq_bp)
    app.register_blueprint(contact_bp)
    app.register_blueprint(videos_bp)
    app.register_blueprint(upload_bp)
    app.register_blueprint(about_bp)

    
    # CORS跨域
    cors.init_app(app, 
                  origins=app.config.get('CORS_ORIGINS', ['*']),
                  supports_credentials=True)
    
    # 日志配置
    init_logging(app)
    
    # JWT配置
    configure_jwt(app)


def init_logging(app):
    """初始化日志配置"""
    
    if not app.debug and not app.testing:
        # 创建日志目录
        log_dir = app.config.get('LOG_DIR', 'logs')
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        
        # 应用日志
        app_log_file = os.path.join(log_dir, 'app.log')
        app_handler = RotatingFileHandler(
            app_log_file, 
            maxBytes=10 * 1024 * 1024,  # 10MB
            backupCount=10
        )
        app_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        ))
        app_handler.setLevel(logging.INFO)
        app.logger.addHandler(app_handler)
        
        # 错误日志
        error_log_file = os.path.join(log_dir, 'error.log')
        error_handler = RotatingFileHandler(
            error_log_file,
            maxBytes=10 * 1024 * 1024,  # 10MB
            backupCount=5
        )
        error_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        ))
        error_handler.setLevel(logging.ERROR)
        app.logger.addHandler(error_handler)
        
        # API访问日志
        api_log_file = os.path.join(log_dir, 'api.log')
        api_handler = RotatingFileHandler(
            api_log_file,
            maxBytes=50 * 1024 * 1024,  # 50MB
            backupCount=10
        )
        api_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(remote_addr)s %(method)s %(url)s %(status_code)s %(response_time)s'
        ))
        
        # 创建API日志记录器
        api_logger = logging.getLogger('api')
        api_logger.addHandler(api_handler)
        api_logger.setLevel(logging.INFO)
        
        app.logger.setLevel(logging.INFO)
        app.logger.info('应用启动')


def configure_jwt(app):
    """配置JWT"""
    
    @jwt.expired_token_loader
    def expired_token_callback(jwt_header, jwt_payload):
        return {
            'error': 'Token已过期',
            'code': 'TOKEN_EXPIRED'
        }, 401
    
    @jwt.invalid_token_loader
    def invalid_token_callback(error):
        return {
            'error': '无效的Token',
            'code': 'INVALID_TOKEN'
        }, 401
    
    @jwt.unauthorized_loader
    def missing_token_callback(error):
        return {
            'error': '缺少认证Token',
            'code': 'MISSING_TOKEN'
        }, 401
    
    @jwt.needs_fresh_token_loader
    def token_not_fresh_callback(jwt_header, jwt_payload):
        return {
            'error': '需要新的Token',
            'code': 'FRESH_TOKEN_REQUIRED'
        }, 401
    
    @jwt.revoked_token_loader
    def revoked_token_callback(jwt_header, jwt_payload):
        return {
            'error': 'Token已被撤销',
            'code': 'TOKEN_REVOKED'
        }, 401